package com.dzjcloud.dzj.common.core.exception;



import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.exceptions.ValidateException;
import cn.hutool.core.util.StrUtil;
import com.dzjcloud.dzj.common.core.enums.ResultEnum;
import com.dzjcloud.dzj.common.core.exception.HandleException;
import com.dzjcloud.dzj.common.core.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.nio.file.AccessDeniedException;
import java.util.List;

/**
 * <h3>springbootdemo</h3>
 * <p>全局异常处理类</p>
 *
 * @author : DongZeJian
 * @date : 2020-04-28 11:41
 **/
@RestControllerAdvice
@Slf4j
public class GlovalExceptionHandler {



    @ExceptionHandler(AccessDeniedException.class)
    public R accessDeniedException(AccessDeniedException e){
        return R.failed(e.getMessage());
    }



    /**
     *  登录拦截异常
     *
     * @param e
     * @return
     */
    /*@ExceptionHandler(NotLoginException.class)
    public R notLoginException(NotLoginException e){
        return new R(ResultEnum.TOKEN_LOSE_EFFICACY);
    }*/

    /**
     * 忽略参数异常处理器
     *
     * @param e 忽略参数异常
     * @return ResponseResult
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
        public R parameterMissingExceptionHandler(MissingServletRequestParameterException e) {
        log.error("{}", e);
        return new R(ResultEnum.ERROR_CODE.getCode(), "请求参数不能为空");
    }

    /**
     * 缺少请求体异常处理器
     *
     * @param e 缺少请求体异常
     * @return ResponseResult
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public R parameterBodyMissingExceptionHandler(HttpMessageNotReadableException e) {
        log.error("", e);
        return new R(ResultEnum.ERROR_CODE.getCode(), "{}参数体不能为空");
    }

    /**
     * 参数效验异常处理器
     *
     * @param e 参数验证异常
     * @return ResponseInfo
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public R parameterExceptionHandler(MethodArgumentNotValidException e) {
        log.error("", e);
        // 获取异常信息
        BindingResult exceptions = e.getBindingResult();
        // 判断异常中是否有错误信息，如果存在就使用异常中的消息，否则使用默认消息
        if (exceptions.hasErrors()) {
            List<ObjectError> errors = exceptions.getAllErrors();
            if (!errors.isEmpty()) {
                // 这里列出了全部错误参数，按正常逻辑，只需要第一条错误即可
                FieldError fieldError = (FieldError) errors.get(0);
                return new R(ResultEnum.ERROR_CODE.getCode(), fieldError.getDefaultMessage());
            }
        }
        return new R(ResultEnum.ERROR_CODE);
    }

    /**
     * 抛出异常处理器
     *
     * @param e 抛出参数
     * @return ResponseInfo
     */
    @ExceptionHandler(HandleException.class)
    public R paramThrowException(HandleException e) {
        log.error("", e);
        if (StrUtil.isNotEmpty(e.getMessage())) {
            return new R(e.getCode(), e.getMessage());
        }
        return new R(ResultEnum.INTER_ERROR);
    }

    /**
     * 405异常处理器
     *
     * @param e
     * @return
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public R param405Exception(HttpRequestMethodNotSupportedException e) {
        log.error("", e);
        return new R(ResultEnum.REQUEST_METHOD_ERROR);
    }



    @ExceptionHandler(ConstraintViolationException.class)
    public R constraintViolationException(ConstraintViolationException e){
        log.error("参数校验",e);
        String errMsg="";
        for (ConstraintViolation<?> constraintViolation : e.getConstraintViolations()) {
            errMsg+=constraintViolation.getMessageTemplate()+",";
        }
        return new R(ResultEnum.ERROR_CODE.getCode(),errMsg.substring(0,errMsg.length()-1));
    }

    @ExceptionHandler(ValidateException.class)
    public R ValidateException(ValidateException e){
        log.error("异常------》{}", ExceptionUtil.stacktraceToString(e));
        return R.failed(e.getMessage());
    }


    /**
     * 统一500异常处理器
     *
     * @param e 父类异常
     * @return
     */
    @ExceptionHandler(Exception.class)
    public R param500Exception(Exception e) {
        log.error("", e);
        if (StrUtil.isNotEmpty(e.getMessage())) {
            return new R(ResultEnum.ERROR_CODE.getCode(), e.getMessage());
        }
        return new R(ResultEnum.INTER_ERROR);
    }

}
